﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using Emgu.CV;
using Emgu.Util;
using Emgu.CV.Structure;
using System.Drawing.Imaging;


namespace My_EMGU_Program
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog Openfile = new OpenFileDialog();
            if (Openfile.ShowDialog() == DialogResult.OK)
            {
                string fileName = Openfile.FileName;
                //string fileName = @"D:\!_Ohh\!_Master Project\SourceCode\EarringsRecommendationWeb\EarringsRecommendationWeb\Upload\IMG_20141125_164806.jpg";
                //Load the image from file
                //Image<Bgr, Byte> img = new Image<Bgr, byte>(fileName);
                //Image<Bgr, Byte> imgResult = img.Resize(400, 400, Emgu.CV.CvEnum.INTER.CV_INTER_LINEAR, true);
                Image<Bgr, Byte> img = new Image<Bgr, byte>(fileName).Resize(400, 400, Emgu.CV.CvEnum.INTER.CV_INTER_LINEAR, true);

                //Convert the image to grayscale and filter out the noise
                Image<Gray, Byte> gray = img.Convert<Gray, Byte>().PyrDown().PyrUp();

                
                //Image originalImage = (Image)origin;

                //Adjust Brightness
                Bitmap originalImage = gray.ToBitmap();

                pictureBox1.Image = img.ToBitmap();
                //pictureBox1.Image = newImg;

                Gray cannyThreshold = new Gray(180);
                Gray cannyThresholdLinking = new Gray(120);
                Gray circleAccumulatorThreshold = new Gray(120);

                CircleF[] circles = gray.HoughCircles(
                    cannyThreshold,
                    circleAccumulatorThreshold,
                    2.0, //Resolution of the accumulator used to detect centers of the circles
                    20.0, //min distance
                    20, //min radius
                    0 //max radius
                    )[0]; //Get the circles from the first channel
                
                float step = 0.5f;
                while (circles.Length > 1)
                {
                    
                    Bitmap newImg = this.DecreaseBrightness(originalImage, step);
                    Image<Bgr, Byte> Nimg = new Image<Bgr, byte>(newImg);

                    gray = Nimg.Convert<Gray, Byte>();//.PyrDown().PyrUp();
                    circles = gray.HoughCircles(
                    cannyThreshold,
                    circleAccumulatorThreshold,
                    2.0, //Resolution of the accumulator used to detect centers of the circles
                    20.0, //min distance
                    20, //min radius
                    0 //max radius
                    )[0]; //Get the circles from the first channel

                    step = step + 0.1f;
                }

                if (circles.Length == 0)
                {
                    circleImageBox.Image = null;
                    //error message
                    return;
                }
                //Image<Gray, Byte> cannyEdges = gray.Canny(cannyThreshold, cannyThresholdLinking);
                //LineSegment2D[] lines = cannyEdges.HoughLinesBinary(
                //    1, //Distance resolution in pixel-related units
                //    Math.PI / 45.0, //Angle resolution measured in radians.
                //    20, //threshold
                //    30, //min Line width 30
                //    10 //gap between lines 10
                //    )[0]; //Get the lines from the first channel

                #region Find triangles and rectangles
                //List<Triangle2DF> triangleList = new List<Triangle2DF>();
                //List<MCvBox2D> boxList = new List<MCvBox2D>();

                //using (MemStorage storage = new MemStorage()) //allocate storage for contour approximation
                //    for (Contour<Point> contours = cannyEdges.FindContours(); contours != null; contours = contours.HNext)
                //    {
                //        Contour<Point> currentContour = contours.ApproxPoly(contours.Perimeter * 0.05, storage);

                //        if (contours.Area > 250) //only consider contours with area greater than 250
                //        {
                //            if (currentContour.Total == 3) //The contour has 3 vertices, it is a triangle
                //            {
                //                Point[] pts = currentContour.ToArray();
                //                triangleList.Add(new Triangle2DF(
                //                   pts[0],
                //                   pts[1],
                //                   pts[2]
                //                   ));
                //            }
                //            else if (currentContour.Total == 4) //The contour has 4 vertices.
                //            {
                //                #region determine if all the angles in the contour are within the range of [80, 100] degree
                //                bool isRectangle = true;
                //                Point[] pts = currentContour.ToArray();
                //                LineSegment2D[] edges = PointCollection.PolyLine(pts, true);

                //                for (int i = 0; i < edges.Length; i++)
                //                {
                //                    double angle = Math.Abs(
                //                       edges[(i + 1) % edges.Length].GetExteriorAngleDegree(edges[i]));
                //                    if (angle < 80 || angle > 100)
                //                    {
                //                        isRectangle = false;
                //                        break;
                //                    }
                //                }
                //                #endregion

                //                if (isRectangle) boxList.Add(currentContour.GetMinAreaRect());
                //            }
                //        }
                //    }
                #endregion

                //pictureBox1.Image = img.ToBitmap();

                //#region draw triangles and rectangles
                //Image<Bgr, Byte> triangleRectangleImage = img.CopyBlank();
                //foreach (Triangle2DF triangle in triangleList)
                //    triangleRectangleImage.Draw(triangle, new Bgr(Color.DarkBlue), 2);
                //foreach (MCvBox2D box in boxList)
                //    triangleRectangleImage.Draw(box, new Bgr(Color.DarkOrange), 2);
                //triangleRectangleImageBox.Image =  triangleRectangleImage.ToBitmap();
                //#endregion

                #region draw circles
                Image<Bgr, Byte> circleImage = img.CopyBlank();
                foreach (CircleF circle in circles)
                    circleImage.Draw(circle, new Bgr(Color.Yellow),1);
                circleImageBox.Image = circleImage.ToBitmap();

                //Image<Bgr, Byte> circleImage = img.CopyBlank();
                //circleImage.Draw(circles[0], new Bgr(Color.Brown), 2);              
                //circleImageBox.Image = circleImage.ToBitmap();

                #endregion

                int width = Convert.ToInt32(circles[0].Radius) * 2;
                MessageBox.Show( width.ToString());


                //>> จาก Visio  CD = 38 ได้ตัวคูณ = 0.18 ต่างหู = 136
                //>> ค่าขนาด CD ที่หาได้จะต้องนำมาเทียบอัตราส่วนหาตัวคูณเพื่อนำไปปรับขนาดต่างหู
                //>> เช่น CD = 76 ตัวคูณจะได้เท่ากับ (0.18/38)*76 จากนั้นนำไปคูณกับ ขนาดต่างหู

                //#region draw lines
                //Image<Bgr, Byte> lineImage = img.CopyBlank();
                //foreach (LineSegment2D line in lines)
                //    lineImage.Draw(line, new Bgr(Color.Green), 2);
                //lineImageBox.Image = lineImage;
                //#endregion
            }
        }

        private Bitmap DecreaseBrightness(Bitmap original, float decreaseStep)
        {
            Bitmap originalImage= original;
            Bitmap adjustedImage = new Bitmap(original.Width,original.Height);
            float brightness = 1.0f; 
            float contrast = 1.0f; 
            float gamma = 1.0f; 

            float adjustedBrightness = brightness - decreaseStep;
            // create matrix that will brighten and contrast the image
            float[][] ptsArray ={
            new float[] {contrast, 0, 0, 0, 0}, // scale red
            new float[] {0, contrast, 0, 0, 0}, // scale green
            new float[] {0, 0, contrast, 0, 0}, // scale blue
            new float[] {0, 0, 0, 1.0f, 0}, // don't scale alpha
            new float[] {adjustedBrightness, adjustedBrightness, adjustedBrightness, 0, 1}};

            ImageAttributes imageAttributes = new ImageAttributes();
            imageAttributes.ClearColorMatrix();
            imageAttributes.SetColorMatrix(new ColorMatrix(ptsArray), ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
            imageAttributes.SetGamma(gamma, ColorAdjustType.Bitmap);
            Graphics g = Graphics.FromImage(adjustedImage);
            g.DrawImage(originalImage, new Rectangle(0, 0, adjustedImage.Width, adjustedImage.Height)
                , 0, 0, originalImage.Width, originalImage.Height,
                GraphicsUnit.Pixel, imageAttributes);
                        
            return adjustedImage;
        }

        private void circleImageBox_Click(object sender, EventArgs e)
        {

        }
    }
}
